
//
//  MonsterTroop.cpp
//  fingeradvanture
//
//  Created by shuaibincheng on 16/5/7.
//
//

#include "MonsterTroopFactory.hpp"
#include "Utils.hpp"
#include "TroopAction.hpp"
#include "TroopStyle.hpp"
#include "TroopForm.hpp"


const int MonsterTroopFactory::TROOP_MAX_MONSTERS = 5;

MonsterTroopFactory *MonsterTroopFactory::factory = 0;
MonsterTroopFactory *MonsterTroopFactory::getInstance()
{
    if(!factory)
        factory = new MonsterTroopFactory;
    return factory;
}

Vector<Node *> MonsterTroopFactory::spawn(b2World *world)
{
    //确定怪物组中怪物的个数
    auto monsterNum = this->randomNumberOfMonsters();
    
    TroopFormType formType = TROOP_INVALID_TROOP_FORM;
    TroopForm *form = 0;
    //根据怪物的个数确定所要采用的队形
    if(monsterNum == 1)
    {
        formType = TROOP_SINGLE_FORM;
    }
    else if(monsterNum > 1)
    {
        //根据怪物的个数确定候选的组队方式
        std::vector<TroopFormType> availableForms = this->availableTroopFormsByNumOfMonster(monsterNum);
        if(!availableForms.size())
            return Vector<Node *>(0);
        //从候选队形中确实怪物要采用的队形
        formType = this->randomTroopFormFromAvailableForms(availableForms);
    }
    else
    {
        //怪物个数有问题, 返加空队伍
        return Vector<Node *>(0);
    }
    form = TroopForm::getTroopFormByType(formType);  //现在怪物组有了队形
    form->setNumOfMonster(monsterNum);  //设置当前队形中monster的个数
    
    //根据队形确定队形的风格
    auto troopStyleType = randomTroopStyleTypeForTroopByForm(form);
    TroopStyle *style = TroopStyle::getTroopStyleByType(troopStyleType, monsterNum);
    form->setStyle(style);
    //根据队伍风格确定要采用的动作
    auto troopActionStyle = randomTroopActionTypeForTroopByForm(form);
    TroopAction *action = TroopAction::getActionByType(troopActionStyle, monsterNum);
    
    form->setAction(action);
    action->setForm(form);
    
    //开始征征召怪物
    style->reset();
    while(style->hasNextMember())
    {
        auto type = style->nextMemberType();
        Node *monster = MonsterDen::getInstance()->callOfDuty(world, type);
        form->join(monster);
    }
    form->group();
    form->train();
    
    return form->rollout();
}

int MonsterTroopFactory::randomNumberOfMonsters()
{
    return Utils::random_int(TROOP_MAX_MONSTERS) + 1;
}

TroopFormType MonsterTroopFactory::chooseTroopFormByNumOfMonster(int num)
{
    return TROOP_INVALID_TROOP_FORM;
}

std::vector<TroopFormType> MonsterTroopFactory::availableTroopFormsByNumOfMonster(int num)
{
    std::vector<TroopFormType> forms;
    if(num == 1)
    {
        forms.push_back(TROOP_SINGLE_FORM);
    }
    else if (num > 1 && num <= 3)
    {
        forms.push_back(TROOP_LINE_FORM);
    }
    else if (num > 3 && num <= 5)
    {
        forms.push_back(TROOP_LINE_FORM);
        forms.push_back(TROOP_SQUARE_FORM);
        if(num % 2)
            forms.push_back(TROOP_CROSS_FORM);
    }
    else if (num > 5 && num <= 6)
    {
        forms.push_back(TROOP_HEXAGON_FORM);
    }
    else if(num == 7)
    {
        forms.push_back(TROOP_CROSS_FORM);
        forms.push_back(TROOP_HEXAGON_FORM);
    }
    
    return forms;
}

TroopFormType MonsterTroopFactory::randomTroopFormFromAvailableForms(const std::vector<TroopFormType> &forms)
{
    auto index = Utils::random_int((int)forms.size());
    return forms.at(index);
}

int MonsterTroopFactory::randomNumOfMonsterTypeForTroopFrom(const TroopForm *form)
{
    int maxTypes = form->getMaxNumOfMonsterTypes();
    if(maxTypes == 1)
        return 1;
    return Utils::random_int(maxTypes) + 1;
}

std::vector<MonsterType> MonsterTroopFactory::randomMonsterTypes(const std::vector<MonsterType> &availables, int num)
{
    std::vector<MonsterType> types;
    for(int i = 0; i < num; i++)
    {
        while(true)
        {
            auto j = Utils::random_int(availables.size());
            auto formType = availables[j];
            auto it = std::find(availables.begin(), availables.end(), formType);
            if(it == availables.begin())
            {
                types.push_back(*it);
                break;
            }
        }
        
    }
    return types;
}

void MonsterTroopFactory::randomActionForMonsterByForm(Node *monster, TroopForm *form)
{
    
}

void MonsterTroopFactory::randomActionForTroopByForm(Node *troop, TroopForm *form)
{
    
}

TroopStyleType MonsterTroopFactory::randomTroopStyleTypeForTroopByForm(TroopForm *form)
{
    auto types = form->allowedTroopStyles();
    auto index = Utils::random_int(types.size());
    return types[index];
}
TroopActionStyle MonsterTroopFactory::randomTroopActionTypeForTroopByForm(TroopForm *form)
{
    auto types = form->allowedTroopActionStyle();
    auto index = Utils::random_int(types.size());
    return types[index];
}





